import socket
import time
import asyncio
import logging
from collections import deque
import socket

# 使用统一的日志配置
from fastapiApp.setting.logger_config import get_test_logger

logger = get_test_logger()

async def async_udp_recv():
    # 创建异步 UDP 客户端实例
    client = SimpleUDPClient('127.0.0.1', 20000, timeout=3, timesend=0.3)

    try:
        # 启动客户端和超时检查
        await asyncio.gather( client.start() )
    except KeyboardInterrupt:
        logging.error("\n收到中断信号,正在停止客户端...")
        client.stop()
    except Exception as e:
        logging.error(f"程序发生错误: {e}")
        client.stop()

class SimpleUDPClient:
    def __init__(self, server_host='127.0.0.1', server_port=12345, timeout=1.0 ,timesend = 0.5):
        self.server_host = server_host
        self.server_port = server_port
        self.timeout = timeout  # 响应超时时间(秒)
        self.timesend = timesend  # 发送间隔时间
        self.sock = None
        self.pending_requests = deque(maxlen=10)  # 保留最近10个待响应请求
        self.is_running = False

    async def start(self):
        """启动异步 UDP 客户端"""
        # 创建 UDP socket
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.setblocking(False)

        # 绑定到任意可用端口
        self.sock.bind(('0.0.0.0', 0))
        local_port = self.sock.getsockname()[1]
        logging.debug(f"UDP 客户端已启动，本地端口: {local_port}")
        logging.debug(f"目标服务器: {self.server_host}:{self.server_port}")
        logging.debug(f"发送间隔: {self.timesend}秒, 超时时间: {self.timeout}秒")

        self.is_running = True

        # 创建发送和接收任务
        send_task = asyncio.create_task(self.send_loop())
        receive_task = asyncio.create_task(self.receive_loop())
        timeout_task = asyncio.create_task(self.timeout_checker_loop())

        try:
            # 等待任务完成
            await asyncio.gather(send_task, receive_task,timeout_task)
        except asyncio.CancelledError:
            logging.warning("errorcode:E0001 - 任务异常 程序异常退出")
        finally:
            self.stop()

    async def send_loop(self):
        """定时发送数据的循环"""
        while self.is_running:
            try:
                # 创建消息并记录发送时间
                timestamp = time.time()
                message = f"sendtime: {timestamp}"
                data = message.encode('utf-8')

                # 发送数据
                loop = asyncio.get_event_loop()
                await loop.sock_sendto(self.sock, data, (self.server_host, self.server_port))
                logging.debug(f"已发送: {message}")

                # 记录待响应请求
                self.pending_requests.append({
                    'send_time': timestamp,
                    'data': data
                })

                # 等待0.5秒
                await asyncio.sleep(self.timesend)

            except Exception as e:
                logging.warning(f"errorcode:E002 - 发送数据时发生错误,{e}")
                await asyncio.sleep(1)  # 出错时等待一秒再继续

    async def receive_loop(self):
        """接收响应的循环"""
        loop = asyncio.get_event_loop()
        while self.is_running:
            try:
                # 接收数据
                data, addr = await loop.sock_recvfrom(self.sock, 1024)

                # 处理响应
                await self.process_response(data, addr)

            except asyncio.CancelledError:
                break
            except Exception as e:
                logging.warning(f"errorcode:E002 - 接收数据时发生错误: {e}")
                await asyncio.sleep(0.1)  # 出错时短暂等待

    async def process_response(self, data: bytes, addr: tuple):
        """处理接收到的响应"""
        response_text = data.decode('utf-8')

        # 查找匹配的请求
        for i, request in enumerate(self.pending_requests):
            # 简单检查响应是否包含请求的时间戳
            if str(request['send_time']) in response_text:
                rtt = (time.time() - request['send_time']) * 1000  # 转换为毫秒
                logging.debug(f"收到响应: {response_text}, RTT: {rtt:.2f}ms")
                # 从待处理请求中移除
                if i < len(self.pending_requests):
                    self.pending_requests.remove(request)
                return

        logging.warning(f"收到未知响应: {response_text} 来自 {addr}")

    async def timeout_checker_loop(self):
        """创建超时检查任务"""
        while self.is_running:
            try:
                self.check_timeouts()
                await asyncio.sleep(0.5)  # 每0.5秒检查一次超时
            except Exception as e:
                logging.warning(f"errorcode:E003 - 检查任务发生错误,{e}")
                await asyncio.sleep(0.5)  # 出错时等待一秒再继续

    def check_timeouts(self):
        """检查超时的请求"""
        current_time = time.time()
        timed_out = []

        for request in self.pending_requests:
            if current_time - request['send_time'] > self.timeout:
                timed_out.append(request)
                logging.info(f"请求超时: 发送时间 {request['send_time']}")

        # 移除超时的请求
        for request in timed_out:
            if request in self.pending_requests:
                self.pending_requests.remove(request)

    def stop(self):
        """停止客户端"""
        self.is_running = False
        if self.sock:
            self.sock.close()
        logging.debug("UDP 客户端已停止")
